package com.csea.lock.rest;


import com.csea.lock.mapper.ProductMapper;
import com.csea.lock.pojo.ProductEntity;
import com.csea.lock.service.JmService;
import com.csea.lock.util.RedisLock;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author Csea
 * @since 2020-07-15
 */
@RestController
@RequestMapping("/csea/product")
@RequiredArgsConstructor
@Slf4j
public class ProductController {

    private final ProductMapper productMapper;

    /**
     * Mysql 的分布式锁
     *
     * @return
     * @throws Exception
     */
    @RequestMapping("mysql/singleLock")
    @Transactional(rollbackFor = Exception.class)
    public String mysqlSingleLock() throws Exception {
        log.info("进入了方法");
        ProductEntity selectLock = productMapper.selectLock("苹果");
        if (StringUtils.isEmpty(selectLock)) {
            throw new Exception("没有分布式锁");
        }
        log.info("拿到了锁");

        Thread.sleep(5000);

        return "完成了";
    }

    private final RedisTemplate redisTemplate;

    /**
     * Redis实现分布式锁
     *
     * @return
     */
    @GetMapping("/redis/lock")
    public String redisLock() {
        log.info("进入了方法");
        String key = "Csea";

        // JDK1.7之后新增的写法
        try (RedisLock lock = new RedisLock(redisTemplate, key, 30)) {
            if (lock.getLock()) {
                Thread.sleep(5000);
                log.info("拿到了锁");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("执行结束");
        return "执行结束";
    }

    private final RedissonClient redissonClient;

    /**
     * Redisson实现分布式锁
     *
     * @return
     */
    @GetMapping("/redisson/lock")
    public String redissonLock() {
        RLock lock = redissonClient.getLock("Csea");
        log.info("进入了方法");
        try {
            lock.lock(30, TimeUnit.SECONDS);
            log.info("拿到了锁");
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        log.info("执行结束");
        return "执行结束";
    }

    private final JmService jmService;

    /**
     * 利用Redisson进行秒杀压测 Demo
     *
     * @param productId
     * @return
     */
    @GetMapping("/redisson/query/{productId}")
    public String redissonQuery(@PathVariable String productId) {
        return jmService.querySecKillProductInfo(productId);
    }

    @GetMapping("/redisson/order/{productId}")
    public String redissonSkill(@PathVariable String productId) {
        jmService.secKillProject(productId);
        return jmService.querySecKillProductInfo(productId);
    }
}
